GeoHash的产生
我们用x,y坐标轴表示你的位置,当我们查看附近的人这个功能的时候,就要对一定范围的人查询,如果放在数据里面,这么算的。
select id from positions where x0-r < x < x0+r and y0-r < y < y0+r
但是当数据量大,并发量大的时候就会存在性能瓶颈。
业界有个算法将经纬度2维坐标转换为一维整数,当我们想要计算附近的人的时候,我们只要计算这个线上的点就好了。编码后,二维坐标变成了整数,但是同时整数也可以重新还原坐标。GeoHash算法会对整数进行编码,生成一个字符串,然后放到zset里面。这个字符串作为score,value是元素的key.
geoadd company 116.48105 39.996794 juejin
我们用这个geoadd来加入到zset里面,redis会按照上面的算法将其2个数字转换为一个score,然后存进去。
geodist company juejin ireader km
这个是计算2个地点的距离。
georadiusbymember company ireader 20 km count 3 asc
这个是查询company这个zset里面 ireader,20km范围内最多3个元素的正排序,包括自身。
scan
keys codess*
找出所有以codess开头的key。但是有缺点,数据量太大,会让服务器卡顿,一长串,数据太多。不好看,不好处理。时间复杂度为o(n).
后面多了个scan:
1多了limit参数,可控了
2通过游标分步进行进行。不阻塞线程。
3.返回的结果可能会有重复,需要客户端去重复,这点非常重要;
4.遍历的过程中如果有数据修改,改动后的数据能不能遍历到是不确定的;
5.单次返回的结果是空的并不意味着遍历结束,而要看返回的游标值是否为零;
scan 参数提供了三个参数,第一个是 cursor 整数值,第二个是 key 的正则模式,第三个是遍历的 limit hint。第一次遍历时,cursor 值为 0,然后将返回结果中第一个整数值作为下一次遍历的 cursor。一直遍历到返回的 cursor 值为 0 时结束。
limit 不是限定返回结果的数量,而是限定服务器单次遍历的字典槽位数量(约等于)。如果将 limit 设置为 10,你会发现返回结果是空的,但是游标值不为零,意味着遍历还没结束。
key 字典
redis里面所有的key存在一个很大的字典里面,类似于hashmap,sacn指令返回的游标就是第一维数组的位置索引,我们将这个位置索引称为槽 (slot)。如果不考虑字典的扩容缩容,直接按数组下标挨个遍历就行了。limit 参数就表示需要遍历的槽位数,之所以返回的结果可能多可能少,是因为不是所有的槽位上都会挂接链表,有些槽位可能是空的,还有些槽位上挂接的链表上的元素可能会有多个。每一次遍历都会将 limit 数量的槽位上挂接的所有链表元素进行模式匹配过滤后,一次性返回给客户端。